<?php

namespace chick1993\util;

use chick1993\util\libs\exceptions\RuntimeException;

class Utils
{
    /**
     * excel 时间戳转unix 时间戳
     * @param $val
     * @return int
     */
    static public function excelStampToUnix($val): int
    {
        if (is_numeric($val)) {
            $unixTimestamp = ($val - 70 * 365 - 19) * 86400 - 8 * 3600;
        } else {
            $unixTimestamp = strtotime($val);
        }
        return (int)$unixTimestamp;
    }

    /**
     * excel 时间戳转unix 时间戳
     * @param $val
     * @param string $format
     * @return string
     */
    static public function excelStampToDate($val, string $format = 'Y-m-d H:i:s'): string
    {
        if (empty($val)) return '';
        $unixTimestamp = self::excelStampToUnix($val);
        return (string)date($format, $unixTimestamp);
    }

    /**
     * 索引转单元格 0,0->A1; 1,1->B2
     * @param int $col 列序号，0开始
     * @param int $row 行号，0开始
     * @return string
     */
    static public function cellFromIndex(int $col, int $row): string
    {
        return self::colFromIndex($col) . ($row + 1);
    }

    /**
     * 单元格转索引 A1->0,0; B2->1,1
     * @param string $cell
     * @return array{col:int,row:int}
     */
    static public function cellToIndex(string $cell): array
    {
        $preg = '/^([a-zA-Z]+)(\d+)$/';
        $res = preg_match($preg, $cell, $matches);
        if (!$res || count($matches) != 3) {
            throw new RuntimeException('单元格错误');
        }
        $col = self::colToIndex($matches[1]);
        $row = $matches[2];
        return [
            'col' => $col,
            'row' => $row,
        ];
    }

    /**
     * 列名转索引 A->0; B->1
     * @param string $str 列名 A列-0
     * @return int
     */
    static public function colToIndex(string $str): int
    {
        $num = 0;
        $str = strtoupper($str);
        $strArr = str_split($str, 1);
        $length = count($strArr);
        foreach ($strArr as $k => $v) {
            $num += ((ord($v) - ord('A') + 1) * pow(26, $length - $k - 1));
        }
        return (int)$num - 1;
    }

    /**
     * 列索引转列名 0->A,1->B
     * @param int $num 列序号 0-A列
     * @return string
     */
    static public function colFromIndex(int $num): string
    {
        $az = 26;
        $m = (int)($num % $az);
        $q = (int)($num / $az);
        $letter = chr(ord('A') + $m);
        if ($q > 0) {
            return self::colFromIndex($q - 1) . $letter;
        }
        return $letter;
    }

    /**
     * 字符串转bool，不能转换的原样返回
     * @param bool|string $str
     * @return bool|string
     */
    static public function strToBool($str)
    {
        if (is_bool($str)) {
            return $str;
        }
        $bool = strtolower(trim($str));
        if ('true' === $bool || 'on' === $bool || '1' === $bool) {
            $str = true;
        } else if ('false' === $bool || 'off' === $bool || '0' === $bool) {
            $str = false;
        }
        return $str;
    }

    /**
     * 文本文件编码转换
     * @param string $filename 文件路径
     * @param string $toEncoding
     * @param string|string[] $fromEncoding
     * @return bool
     */
    static public function textFileConvert(string $filename, string $toEncoding = 'utf-8', $fromEncoding = 'gbk'): bool
    {
        $temp = $filename . '.tmp';
        rename($filename, $temp);
        $tmpH = fopen($temp, 'r+');
        $handle = fopen($filename, 'a+');
        if (!$tmpH) {
            throw new RuntimeException('读取文件失败：' . $temp);
        }
        if (!$handle) {
            fclose($tmpH);
            rename($temp, $filename);
            throw new RuntimeException('无法创建文件 ' . $filename);
        }
        // 定义缓冲区大小
        $buffer = 81920; // 8KB
        while (!feof($tmpH)) {
            $data = fread($tmpH, $buffer);
            if ($data === false) break;
            $cData = mb_convert_encoding($data, $toEncoding, $fromEncoding);
            fwrite($handle, $cData);
        }
        fclose($handle);
        fclose($tmpH);
        @unlink($temp);
        return true;
    }
}